package indi.henry.demo.service.impl;

import java.time.Instant;
import java.util.Optional;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import indi.henry.demo.constant.Constants;
import indi.henry.demo.model.Counter;
import indi.henry.demo.service.CounterService;
import indi.henry.demo.service.RedisService;
import indi.henry.demo.service.ShortenService;
import lombok.RequiredArgsConstructor;

/**
 * Function implementation for counter service
 * 
 * @author Henry Hu
 * @see CounterService
 */
@RequiredArgsConstructor
@Service
public class CounterServiceImpl implements CounterService {

    private final ShortenService shortenService;

    private final RedisService redisService;

    @Override
    public Counter getCurrentByOrigin(String url) {
        url = shortenService.convertUrl(url);
        String id = shortenService.shortUrl(url);
        return redisService.getCounter(Constants.COUNTER_PREFIX.concat(id));
    }

    @Async
    @Override
    public synchronized Counter addGet(String id) {

        Counter counter = Optional.ofNullable(redisService.getCounter(Constants.COUNTER_PREFIX.concat(id))).orElseGet(
            () -> Counter.builder().set(0).get(0).getTime(Instant.now().toEpochMilli()).build());

        long get = counter.getGet();

        counter.setGet(++get);
        counter.setGetTime(Instant.now().toEpochMilli());
        redisService.setCounter(Constants.COUNTER_PREFIX.concat(id), counter);

        return counter;
    }

    @Async
    @Override
    public synchronized Counter addSet(String id) {

        Counter counter = Optional.ofNullable(redisService.getCounter(Constants.COUNTER_PREFIX.concat(id))).orElseGet(
            () -> Counter.builder().set(0).get(0).setTime(Instant.now().toEpochMilli()).build());

        long set = counter.getSet();

        counter.setSet(++set);
        counter.setSetTime(Instant.now().toEpochMilli());
        redisService.setCounter(Constants.COUNTER_PREFIX.concat(id), counter);

        return counter;
    }
}
